/*
 动态引入资源 实现代码
 函数执行顺序:
 ipt->start->loadSrc->loadCss
 					  loadScript
*/
! function (exports, map, mapsear, each) {
	var p = {
		pres: [],
		timeid: null,
		status: 'done',
		loadsrc: {
			/*
			src:{
				status:string in loading|done|merge|pre|loaddes
				in				   加载中|执行完成|合并|预执行|加载依赖项中
				in 	status顺序 loading->pre|merge->loaddes->done
				exports:object
				fns:array in function in err,exports
				scriptend:function in err,exports
				des:array in string 依赖项
			}
			*/
		},
		amd:{}
	};

	function createLoadsrc(src, status) {
		status = status || 'loading'
		p.loadsrc[src] = {
			status: status,
			fns: [],
			scriptend: function () {}
		}
	}

	function loadsrcsFor(src) {
		return p.loadsrc[src];
	}

	function donesrcs(err, exprots, src, fn) {
		p.loadsrc[src].status = 'done';
		p.loadsrc[src].exports = exprots;
		each(p.loadsrc[src].fns, function (t) {
			t(err, exprots)
		});
		fn(err, exprots)
	}

	function loadSrc(src, fn) {
		src = util.toabspath(src);
		var load = loadsrcsFor(src);
		if (load && load.status === 'done') {
			fn(null, load.exports);
			return;
		} else if ((load && load.status === 'loading') || (load && load.status === 'merge')||(load && load.status === 'pre')) {
			load.fns.push(fn);
			return;
		}
		createLoadsrc(src);
		if (~src.split('?')[0].indexOf('.css')) {
			loadCss(src, function (err, node) {
				donesrcs(err, node, src, fn)
			});
		} else if (~src.split('?')[0].indexOf('.js')) {
			p.loadsrc[src].scriptend = fn;
			loadScript(src, function (err, n) {
				if (p.loadsrc[src].status == "loading" || p.loadsrc[src].status == "merge") {
					donesrcs(err, null, src, fn)
				}
			});
		}
	}

	function loadCss(src, fn) {
		var node = document.createElement('link');
		node.rel = 'stylesheet';
		node.href = src;
		util.dochead.insertBefore(node, util.dochead.firstChild);
		if (node.attachEvent) {
			node.attachEvent('onload', function () {
				fn(null, node)
			});
		} else {
			setTimeout(function () {
				poll(node, fn);
			}, 0); // for cache
		}

		function poll(node, callback) {
			var isLoaded = false;
			if (/webkit/i.test(navigator.userAgent)) { //webkit
				if (node['sheet']) {
					isLoaded = true;
				}
			} else if (node['sheet']) { // for Firefox
				try {
					if (node['sheet'].cssRules) {
						isLoaded = true;
					}
				} catch (ex) {
					// NS_ERROR_DOM_SECURITY_ERR
					if (ex.code === 1000) {
						isLoaded = true;
					}
				}
			}
			if (isLoaded) {
				setTimeout(function () {
					callback(null, node);
				}, 1);
			} else {
				setTimeout(function () {
					poll(node, callback);
				}, 10);
			}
		}
	}

	function loadScript(src, fn) {
		var node = document.createElement("script");
		node.setAttribute('async', 'async');
		var timeID
		var supportLoad = "onload" in node
		var onEvent = supportLoad ? "onload" : "onreadystatechange"
		node[onEvent] = function onLoad() {
			if (!supportLoad && !timeID && /complete|loaded/.test(node.readyState)) {
				timeID = setTimeout(onLoad)
				return
			}
			if (supportLoad || timeID) {
				clearTimeout(timeID)
				fn(null, node);
			}
		}
		util.dochead.insertBefore(node, util.dochead.firstChild);
		node.src = src;
		node.onerror = function (e) {
			fn(e);
		}
	}

	function iife(id, des, fn,amd) {
		if (util.type.isFunction(id)) {
			fn = id;
			id = null;
			des = null;
		}
		if (util.type.isArray(id)) {
			fn = des;
			des = id;
			id = null;
		}
		if (util.type.isFunction(des)) {
			fn = des;
			des = null;
		}
		if(p.amd[id])id=p.amd[id]
		var current = util.getCurrentScript() 
        current=current&& current.src;
		if (id) id = util.toabspath(id);
		id = id || current || util.toabspath('/');
		if (!p.loadsrc[id]) createLoadsrc(id, 'pre');
		else p.loadsrc[id].status = 'pre';
		if (id != current) {
			p.loadsrc[id].status = 'merge';
		}
		setTimeout(function () {
			p.loadsrc[id].status = 'loaddes';
			util.map(des, function (next, t, i) {
				if(p.amd[t])t=p.amd[t]
				var path = util.toabspath(t);
				if (p.loadsrc[path] && p.loadsrc[path].status === 'loaddes') { //循环依赖
					next();
					return;
				}
				loadSrc(path, next);
			}, function (err, rs) {
				var modudel = {
					exports: {}
				};
				if(amd){
					modudel.exports=fn.apply(modudel.exports,rs);
				}else{
					fn.apply(modudel.exports, [modudel.exports, modudel].concat(rs));
				}
				donesrcs(err,modudel.exports,id,p.loadsrc[id].scriptend);
			});
		})
	}

	function ipt(src, fn) {
		if(util.type.isObject(src)){
			for(key in src){
				p.amd[key]=src[key];
			}
			return arguments.callee;
		}
		if(p.amd[src])src=p.amd[src]
		p.pres.push({
			src: src,
			fn: fn
		});
		start();
		return arguments.callee;
	}
	ipt.wait = function (fn) {
		p.pres.push({
			fn: fn,
			wait: true
		});
		start();
		return this;
	}
	ipt.ipt = ipt;

	function start() {
		if (p.pres.length == 0 || p.status == 'runing') return;
		clearTimeout(p.timeid);
		p.timeid = setTimeout(function () {
			p.status = "runing";
			var a2rr = [],
				i = 0,
				waitfn = [function () {}];
			each(p.pres, function (t, i1) {
				if (t.wait) {
					waitfn[i] = t.fn;
					i++;
					return;
				}
				a2rr[i] = a2rr[i] || [];
				a2rr[i].push(t);
			});
			p.pres = [];
			mapsear(a2rr, function (end, t, i) {
				map(t, function (end1, t1, i1) {
					loadSrc(t1.src, function (err, node) {
						if (t1.fn) t1.fn(err, node);
						end1(err, node);
					});
				}, function (err, rs) {
					if (waitfn[i]) waitfn[i].apply(null, [err].concat(rs));
					end(err, rs);
				});
			}, function (err, rs) {
				if (err) {
					console.log('diqye-err', err);
					return;
				}
				p.status = 'done';
				start();
			});

		});
	}
	exports.ipt = ipt;
	exports.iife = iife;
	exports.define=function(id,des,fn){
		iife(id,des,fn,true);//amd规范
	};
	exports.define.amd=p.amd;
}(exports, util.map, util.mapsear, util.each);
